//Listing 4. Simple Sound Recording
 
 
/*
 
This example reads from the default PCM device
and writes to standard output for 5 seconds of data.
 
*/
 
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
 
#include <alsa/asoundlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <speex/speex.h>

#define TO_PORT 12345
#define TO_ADDR "192.168.68.188"

/*Holds the state of the encoder*/
void *state;
/*Holds bits so they can be read and written to by the Speex routines*/
SpeexBits bits;

/*The frame size in hardcoded for this sample code but it doesn't have to be*/
#define FRAME_SIZE 160

short in[FRAME_SIZE];
float input[FRAME_SIZE];
char cbits[200];
int nbBytes;
int i, tmp;
char *toaddr;
#if 0
FILE *fout;
#endif
 
struct sockaddr_in addr;
int fd;
     
void init_udp()
{
     /* create what looks like an ordinary UDP socket */
     if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) 
     {
				perror("socket");
				exit(1);
     }

     /* set up destination address */
     memset(&addr,0,sizeof(addr));
     addr.sin_family=AF_INET;
     addr.sin_addr.s_addr=inet_addr(toaddr);
     addr.sin_port = htons(TO_PORT);
}

int main(int argc, char **argv) 
{
	long loops;
	int rc;
	int size;
	snd_pcm_t *handle;
	snd_pcm_hw_params_t *params;
	unsigned int val;
	int dir;
	snd_pcm_uframes_t frames;
	char *buffer;
    #if 0
	char *inFile, *outFile;
    #endif

    if(argc != 2)
    {
        printf("error! usage: catpure 192.168.xxx.xxx\n");
        return;
    }

    toaddr = argv[1];
    #if 0
	outFile = argv[1];
	fout = fopen(outFile, "wb");
    #endif

	init_udp();
	
	printf("%s: 2222222222\n", __FUNCTION__);	
	/*Create a new encoder state in narrowband mode*/
	state = speex_encoder_init(&speex_nb_mode);

	/*Set the quality to 8 (15 kbps)*/
	tmp=8;
	speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp);

	/*Initialization of the structure that holds the bits*/
	speex_bits_init(&bits);
      
	/* Open PCM device for recording (capture). */
	rc = snd_pcm_open(&handle, "default",
		            SND_PCM_STREAM_CAPTURE, 0);
	if (rc < 0) 
	{
    	fprintf(stderr,
            "unable to open pcm device: %s\n",
            snd_strerror(rc));
    	exit(1);
	}
 
	/* Allocate a hardware parameters object. */
	snd_pcm_hw_params_alloca(&params);
	 
	/* Fill it in with default values. */
	snd_pcm_hw_params_any(handle, params);
	 
	/* Set the desired hardware parameters. */
	 
	/* Interleaved mode */
	snd_pcm_hw_params_set_access(handle, params,
		                  SND_PCM_ACCESS_RW_INTERLEAVED);
	 
	/* Signed 16-bit little-endian format */
	snd_pcm_hw_params_set_format(handle, params,
		                          SND_PCM_FORMAT_S16_LE);
	 
	/* Two channels (stereo) */
	snd_pcm_hw_params_set_channels(handle, params, 1);
	 
	/* 44100 bits/second sampling rate (CD quality) */
	val = 8000;
	snd_pcm_hw_params_set_rate_near(handle, params,
		                              &val, &dir);
	 
	/* Set period size to 32 frames. */
	frames = 160;
	snd_pcm_hw_params_set_period_size_near(handle,
		                          params, &frames, &dir);
 
	/* Write the parameters to the driver */
	rc = snd_pcm_hw_params(handle, params);
	if (rc < 0) 
	{
		fprintf(stderr,
		        "unable to set hw parameters: %s\n",
		        snd_strerror(rc));
    	exit(1);
	}
 
	/* Use a buffer large enough to hold one period */
	snd_pcm_hw_params_get_period_size(params,
                                      &frames, &dir);
                                      
	size = frames * 2; /* 2 bytes/sample, 2 channels */
	buffer = (char *) malloc(size);
 
	/* We want to loop for 5 seconds */
	snd_pcm_hw_params_get_period_time(params,
                                         &val, &dir);
	//loops = 50000000L / val;
 
	printf("%s: 99999999\n", __FUNCTION__);	
	//while (loops > 0) {
	while(1)
	{
		//loops--;
		printf(".");
		rc = snd_pcm_readi(handle, buffer, frames);

		if (rc == -EPIPE) 
		{
		  /* EPIPE means overrun */
		  fprintf(stderr, "overrun occurred\n");
		  snd_pcm_prepare(handle);
		} 
		else if (rc < 0) 
		{
		  fprintf(stderr,
				  "error from read: %s\n",
				  snd_strerror(rc));
		} 
		else if (rc != (int)frames) 
		{
		  fprintf(stderr, "short read, read %d frames\n", rc);
		}
		//rc = write(1, buffer, size);
    
    
		#if 1
		//printf("aaaaaaaaaaaaaa\n");
		  /*Copy the 16 bits values to float so Speex can work on them*/
		  for (i=0;i<FRAME_SIZE;i++)
			 input[i] = ((short*)buffer)[i];//in[i];
		//printf("bbbbbbb\n");
		  /*Flush all the bits in the struct so we can encode a new frame*/
		  speex_bits_reset(&bits);
		//printf("cccccccccc\n");
		  /*Encode the frame*/
		  speex_encode(state, input, &bits);
		//printf("ddddddd\n");            
		  /*Copy the bits to an array of char that can be written*/
		  nbBytes = speex_bits_write(&bits, cbits, 200);
		//printf("eeeeeeeeeeeeeeeeeeeeeeeeeee\n");      
		#endif  
      
		#if 0
		/*Write the size of the frame first. This is what sampledec expects but
		it's likely to be different in your own application*/
		fwrite(&nbBytes, sizeof(int), 1, fout);
		/*Write the compressed data*/
		fwrite(cbits, 1, nbBytes, fout);
		#endif
                
		if ((rc=sendto(fd, cbits, nbBytes, 0, (struct sockaddr *) &addr, sizeof(addr))) < 0) 
		{
			   perror("sendto");
			   exit(1);
		}	
		else
		{
			printf("发送%d字节 \n", rc);
		}
				    
		if (rc != nbBytes)
		  fprintf(stderr,
		          "short write: wrote %d bytes\n", rc);
	}
 
	snd_pcm_drain(handle);
	snd_pcm_close(handle);
	free(buffer);
 
	return 0;
}

